// 
// Copyright (c) 2013 Jason Bell
// 
// Permission is hereby granted, free of charge, to any person obtaining a 
// copy of this software and associated documentation files (the "Software"), 
// to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the 
// Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included 
// in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
// 

using System;
using System.Runtime.InteropServices;
using System.Security;

namespace Gharen.GLCore.X11
{

	
	public sealed class glx
	{
		const string Library = "libGL.so.1";
		
        [DllImport(Library, EntryPoint = "glXQueryVersion")]
        public static extern bool QueryVersion(IntPtr dpy, ref int major, ref int minor);
		
		// Returns an array of GLXFBConfig structures.
        [CLSCompliant(false)]
        [DllImport(Library, EntryPoint = "glXChooseFBConfig")]
        unsafe public extern static IntPtr* ChooseFBConfig(IntPtr dpy, int screen, int[] attriblist, out int fbount);
	
		[DllImport(Library, EntryPoint = "glXGetVisualFromFBConfig")]
        public unsafe extern static IntPtr GetVisualFromFBConfig(IntPtr dpy, IntPtr fbconfig);
		
		[DllImport(Library, EntryPoint = "glXQueryExtensionsString")]
        static extern IntPtr QueryExtensionsStringInternal(IntPtr dpy, int screen);
		
		public static string QueryExtensionsString(IntPtr dpy, int screen)
        {
            return Marshal.PtrToStringAnsi(QueryExtensionsStringInternal(dpy, screen));
        }
		
		[DllImport(Library, EntryPoint = "glXGetProcAddress")]
        public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);

        [CLSCompliant(false)]
	    unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs)
        {
            return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs);
        }

        public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int[] attribs)
        {
            unsafe
            {
                fixed (int* attribs_ptr = attribs)
                {
                    return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs_ptr);
                }
            }
        }
		
		[DllImport(Library, EntryPoint = "glXCreateContext")]
        public static extern IntPtr CreateContext(IntPtr dpy, IntPtr vis, IntPtr shareList, bool direct);

        [DllImport(Library, EntryPoint = "glXCreateContext")]
        public static extern IntPtr CreateContext(IntPtr dpy, ref XVisualInfo vis, IntPtr shareList, bool direct);
		
		
        [DllImport(Library, EntryPoint = "glXMakeCurrent")]
        public static extern bool MakeCurrent(IntPtr display, IntPtr drawable, IntPtr context);
		
		[DllImport(Library, EntryPoint = "glXSwapBuffers")]
        public static extern void SwapBuffers(IntPtr display, IntPtr drawable);
	}
	
    internal static class Delegates
    {
        [SuppressUnmanagedCodeSecurity]
        public delegate int SwapIntervalSGI(int interval);
        public static SwapIntervalSGI glXSwapIntervalSGI = null;

        [SuppressUnmanagedCodeSecurity]
        unsafe public delegate IntPtr CreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
        unsafe public static CreateContextAttribsARB glXCreateContextAttribsARB = null;
    }
	
	enum ArbCreateContext : int
    {
        DebugBit = 0x0001,
        ForwardCompatibleBit = 0x0002,
        MajorVersion = 0x2091,
        MinorVersion = 0x2092,
        LayerPlane = 0x2093,
        Flags = 0x2094,
        ErrorInvalidVersion = 0x2095,
    }
}

